package ltd.hxya.novel.book.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ltd.hxya.novel.book.entity.BookCategory;
import ltd.hxya.novel.book.mapper.BookCategoryMapper;
import ltd.hxya.novel.book.service.IBookCategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ltd.hxya.novel.book.vo.BookCategoryVo;
import ltd.hxya.novel.common.anno.SaveNotice;
import ltd.hxya.novel.common.bean.ModuleEnum;
import ltd.hxya.novel.common.bean.OperEnum;
import ltd.hxya.novel.common.constant.redis.RedisConstant;
import ltd.hxya.novel.common.utils.BaseUtils;
import ltd.hxya.novel.common.utils.PageUtils;
import ltd.hxya.novel.common.vo.PageParam;
import ltd.hxya.novel.entity.rowdata.DataPart;
import ltd.hxya.novel.springsecurity.entity.User;
import ltd.hxya.novel.springsecurity.entity.UserDetail;
import ltd.hxya.novel.springsecurity.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 小说类别表 服务实现类
 * </p>
 *
 * @author hxya
 * @since 2022-09-13
 */
@Service
public class BookCategoryServiceImpl extends ServiceImpl<BookCategoryMapper, BookCategory> implements IBookCategoryService {

    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 根据条件查询出分类，并最终将分类添加到Redis中
     *
     * @param categoryCondition
     * @param workDirection
     * @return
     */
    @Override
    public List<BookCategoryVo> listCategory(Integer categoryCondition, Boolean workDirection) {
        //查询Redis中是否有category的信息，如果没有，则查出所有的分类信息并添加到Redis中
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String json = valueOperations.get(RedisConstant.BOOK_CATEGORY_KEY);
        if (StringUtils.isEmpty(json)) {
            //从数据库中查询category的信息
            List<BookCategory> bookCategories = this.baseMapper.selectList(null);
            String bookCategoryJson = JSON.toJSONString(bookCategories);
            //添加到Redis中，并设置过期时间，防止在添加或修改分类是出现意外状况，导致Redis中的信息没能及时修改
            valueOperations.set(RedisConstant.BOOK_CATEGORY_KEY, bookCategoryJson, 10, TimeUnit.MINUTES);
            json = valueOperations.get(RedisConstant.BOOK_CATEGORY_KEY);
        }

        List<BookCategory> bookCategories = JSON.parseObject(json, new TypeReference<List<BookCategory>>() {
        });


        List<BookCategoryVo> bookCategoryVos = null;
        if (!CollectionUtils.isEmpty(bookCategories)) {
            bookCategoryVos = bookCategories.stream().filter(bookCategory -> {
                //从所得到的的信息中过滤得到想要的信息
                if (Objects.equals(bookCategory.getCategoryCondition(), categoryCondition)) {
                    if (workDirection != null && bookCategory.getWorkDirection().equals(workDirection)) {
                        return true;
                    }
                    if (workDirection == null) {
                        return true;
                    }

                    return false;
                }
                return false;
            }).map(bookCategory -> {
                //将过滤后的信息进行封装
                BookCategoryVo bookCategoryVo = new BookCategoryVo();
                BeanUtils.copyProperties(bookCategory, bookCategoryVo);
                return bookCategoryVo;
            }).collect(Collectors.toList());
        }

        return bookCategoryVos;
    }


    /**
     * 查询在分类中是否有该分类，如果没有，则插入该分类
     *
     * @param bookCategory
     */
    @Override
    @SaveNotice(operEnum = OperEnum.SAVE, module = ModuleEnum.CATEGORY_MODULE, message = "添加分类")
    public void insertCategory(BookCategory bookCategory) {
        //根据分类名查询分类
        BookCategory bookCategory1 = getCategoryByName(bookCategory.getName());
        if (bookCategory1 != null) {
            bookCategory.setId(bookCategory1.getId());
            return;
        }
        //如果查询出来的数据为null，则插入数据
        bookCategory.setUpdateTime(LocalDateTime.now());
        bookCategory.setCreateTime(LocalDateTime.now());
        this.save(bookCategory);
        bookCategory.setOperId(bookCategory.getId().toString());
    }

    @Override
    public Page<BookCategory> listBookCategory(BookCategory bookCategory) {
        QueryWrapper<BookCategory> bookCategoryQueryWrapper = new QueryWrapper<>();
        if (bookCategory.getId() != null) {
            bookCategoryQueryWrapper.eq("id", bookCategory.getId());
        }
        if (!StringUtils.isEmpty(bookCategory.getWorkDirection())) {
            bookCategoryQueryWrapper.eq("work_direction", bookCategory.getWorkDirection());
        }
        if (!StringUtils.isEmpty(bookCategory.getName())) {
            bookCategoryQueryWrapper.like("name", bookCategory.getName());
        }

        BaseUtils.compareTime(bookCategoryQueryWrapper, bookCategory);
        PageParam pageParam = PageUtils.getPageParams();
        Page<BookCategory> categoryPage = this.page(new Page<BookCategory>(pageParam.getCurrent(), pageParam.getSize()), bookCategoryQueryWrapper);

        return categoryPage;
    }

    @Override
    public void addCategory(BookCategory bookCategory) {
        bookCategory.setCreateTime(LocalDateTime.now());
        UserDetail principal = SecurityUtils.principal();
        User user = principal.getUser();

        bookCategory.setCreateUserId(user.getUserId());
        this.save(bookCategory);
    }

    @Override
    public void updateCategory(BookCategory bookCategory) {
        bookCategory.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(bookCategory);

    }

    @Override
    public void deleteBatchCategory(String[] ids) {
        List<String> idList = Arrays.asList(ids);
        if (CollectionUtils.isEmpty(idList)){
            return;
        }
        baseMapper.deleteBatchIds(idList);
    }

    @Override
    public BookCategory saveCategory(DataPart dataPart) {

        QueryWrapper<BookCategory> bookCategoryQueryWrapper = new QueryWrapper<>();
        bookCategoryQueryWrapper.eq("name",dataPart.getCatName());
        BookCategory bookCategory = this.baseMapper.selectOne(bookCategoryQueryWrapper);
        if (ObjectUtils.isEmpty(bookCategory)){
            bookCategory = new BookCategory();
            bookCategory.setName(dataPart.getCatName());

            bookCategory.setId(BaseUtils.getRandomId());
            this.baseMapper.insert(bookCategory);

        }
        return bookCategory;
    }

    @Override
    public List<BookCategory> selectList(QueryWrapper<BookCategory> queryWrapper) {
        return baseMapper.selectList(queryWrapper);
    }

    public BookCategory getCategoryByName(String name) {
        QueryWrapper<BookCategory> bookCategoryQueryWrapper = new QueryWrapper<>();
        bookCategoryQueryWrapper.eq("name", name);
        return this.baseMapper.selectOne(bookCategoryQueryWrapper);
    }
}
